package com.ruoyi.user.service.impl;

import java.io.ByteArrayInputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.constant.CommonConst;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.aliyun.FileUploadOssUtils;
import com.ruoyi.framework.util.RedisCacheUtil;
import com.ruoyi.user.dto.*;
import com.ruoyi.user.exception.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.service.IUserService;
import org.springframework.web.multipart.MultipartFile;

/**
 * 用户Service业务层处理
 * 
 * @author ruoyi
 * @date 2020-12-26
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService 
{
    @Autowired
    private UserMapper userMapper;

    public static String defaultAvatar = "";

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Value("${aliyun.default-avatar-path}")
    private String picturePath;

    @Override
    public AjaxResult register(UserRegisterDTO registerDTO) {
        // 判断手机号是否存在
        User userQuery = new User();
        userQuery.setPhone(registerDTO.getPhone());
        userQuery.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(userQuery);
        if (CollUtil.isNotEmpty(users)) {
            return AjaxResult.error(ResultCode.PHONE_EXIST.message());
        }

        if (!verifyCode(registerDTO.getPhone())) {
            return AjaxResult.error(ResultCode.VERIFY_CODE_ERROR.message());
        }

        // 对密码进行加密
        String cyclePassword = EncryptUtil.cycleEncryption(registerDTO.getPassword(), CommonConst.ENCRYPT_TIMES);

        // 插入用户
        User insertUser = new User();
        insertUser.setDelStatus(CommonConst.DEL_FALSE);
        insertUser.setPhone(registerDTO.getPhone());
        insertUser.setAvatar(defaultAvatar);
        // 昵称默认为手机号
        insertUser.setNickName(insertUser.getPhone());
        insertUser.setPassword(cyclePassword);
        insertUser.setUnionId(CommonConst.STRING_EMPTY);
        insertUser.setOpenId(CommonConst.STRING_EMPTY);
        insertUser.setUserStatus(1);
        insertUser.setUserType(1);
        insertUser.setGender(0);
        insertUser.setKeyId(IdGenerator.getId());
        insertUser.setCreateTime(new Date());
        insertUser.setCreateBy(CommonConst.DEFAULT_USER_ID);
        insertUser.setUpdateTime(insertUser.getCreateTime());
        insertUser.setUpdateBy(insertUser.getCreateBy());
        userMapper.insertUser(insertUser);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult registerForward(UserRegisterForwardDTO registerForwardDTO) {
        // 判断手机号是否存在
        User userQuery = new User();
        userQuery.setPhone(registerForwardDTO.getPhone());
        userQuery.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(userQuery);
        if (CollUtil.isNotEmpty(users)) {
            return AjaxResult.error(ResultCode.PHONE_EXIST.message());
        }
        if (!verifyCode(registerForwardDTO.getPhone())) {
            return AjaxResult.error(ResultCode.VERIFY_CODE_ERROR.message());
        }
        return AjaxResult.success();
    }


    @Override
    public AjaxResult sendVerifyCode(SendCodeDTO sendCodeDTO) {
        // TODO 待做
        try{
            String code = SmsUtils.getBindNum();
            SmsUtils.getInstance().smsCode(sendCodeDTO.getPhone(),code);
            redisCacheUtil.set(sendCodeDTO.getPhone(),code,600);
        }catch (Exception e){
            return AjaxResult.error();
        }

        return  AjaxResult.success();
    }

    @Override
    public AjaxResult login(LoginDTO loginDTO) {
        String cyclePassword = EncryptUtil.cycleEncryption(loginDTO.getPassword(), CommonConst.ENCRYPT_TIMES);
        // 通过账号密码去数据库中查找是否存在该用户
        User queryUser = new User();
        queryUser.setPhone(loginDTO.getPhone());
        queryUser.setPassword(cyclePassword);
        queryUser.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(queryUser);
        if (CollUtil.isEmpty(users)) {
            return AjaxResult.error("手机号或者密码错误");
        }
        // 判断用户是否可用
        User user = users.get(0);
        if (CommonConst.USER_FROZEN.equals(user.getUserStatus())) {
            return AjaxResult.error("手机号已被冻结");
        }
        String token = setTokenCache(user.getKeyId());
        setMemberCache(user);
        LoginUserRes res = new LoginUserRes();
        BeanUtils.copyProperties(user, res);
        res.setUserId(String.valueOf(user.getKeyId()));
        res.setToken(token);
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult logout(LogoutDTO logoutDTO) {
        String token = ServletUtils.getRequest().getHeader("x-token");
        removeMemberCache(Long.valueOf(logoutDTO.getUserId()));
        removeTokenCache(token);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult findPasswordForward(FindPasswordForward passwordForward) {
        // 判断手机号是否存在
        User userQuery = new User();
        userQuery.setPhone(passwordForward.getPhone());
        userQuery.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(userQuery);
        if (CollUtil.isEmpty(users)) {
            return AjaxResult.error(ResultCode.PHONE_NOT_EXIST.message());
        }
        if (!verifyCode(passwordForward.getPhone())) {
            return AjaxResult.error(ResultCode.VERIFY_CODE_ERROR.message());
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult findPassword(FindPassword findPassword) {
        // 判断手机号是否存在
        User userQuery = new User();
        userQuery.setPhone(findPassword.getPhone());
        userQuery.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(userQuery);
        if (CollUtil.isEmpty(users)) {
            return AjaxResult.error(ResultCode.PHONE_NOT_EXIST.message());
        }
        if (!verifyCode(findPassword.getPhone())) {
            return AjaxResult.error(ResultCode.VERIFY_CODE_ERROR.message());
        }
        // 对密码进行加密
        String cyclePassword = EncryptUtil.cycleEncryption(findPassword.getPassword(), CommonConst.ENCRYPT_TIMES);
        User userUpdate = new User();
        userUpdate.setKeyId(users.get(0).getKeyId());
        userUpdate.setPassword(cyclePassword);
        userMapper.updateUser(userUpdate);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult updatePassword(UpdatePasswordDTO updatePasswordDTO) {
        Long userId = Long.valueOf(updatePasswordDTO.getUserId());
        String cycleOldPassword = EncryptUtil.cycleEncryption(updatePasswordDTO.getOldPassword(), CommonConst.ENCRYPT_TIMES);
        String cycleNewPassword = EncryptUtil.cycleEncryption(updatePasswordDTO.getNewPassword(), CommonConst.ENCRYPT_TIMES);
        User userQuery = new User();
        userQuery.setKeyId(userId);
        userQuery.setPassword(cycleOldPassword);
        userQuery.setDelStatus(CommonConst.DEL_FALSE);
        List<User> users = userMapper.selectUserList(userQuery);
        // 密码错误
        if (CollUtil.isEmpty(users)) {
            return AjaxResult.error(ResultCode.OLD_PASSWORD_ERROR.message());
        }
        User userUpdate = new User();
        userUpdate.setKeyId(userId);
        userUpdate.setPassword(cycleNewPassword);
        userMapper.updateUser(userUpdate);

        // 删除登录状态和缓存
        String token = ServletUtils.getRequest().getHeader("x-token");
        removeMemberCache(userId);
        removeTokenCache(token);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult updateNickName(UpdateNicknameDTO updateNicknameDTO) {
        Long userId = Long.valueOf(updateNicknameDTO.getUserId());
        User user = userMapper.selectUserById(userId);
        if (Objects.isNull(user)) {
            return AjaxResult.error(ResultCode.USER_NOT_EXIST.message());
        }
        User updateUser = new User();
        updateUser.setKeyId(userId);
        updateUser.setNickName(updateNicknameDTO.getNickName());
        userMapper.updateUser(updateUser);

        user.setNickName(updateNicknameDTO.getNickName());
        setMemberCache(user);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult uploadAvatar(UploadAvatarDTO uploadAvatarDTO) {
        Long userId = Long.valueOf(uploadAvatarDTO.getUserId());
        User user = userMapper.selectUserById(userId);
        if (Objects.isNull(user)) {
            return AjaxResult.error(ResultCode.USER_NOT_EXIST.message());
        }
        String url = uploadFile(uploadAvatarDTO.getFile());
        if (StringUtils.isEmpty(url)) {
            return AjaxResult.error(ResultCode.AVATAR_UPLOAD_ERROR.message());
        }
        User updateUser = new User();
        updateUser.setKeyId(userId);
        updateUser.setAvatar(url);
        userMapper.updateUser(updateUser);

        user.setAvatar(url);
        setMemberCache(user);
        return AjaxResult.success();
    }

    public String uploadFile (MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename();
            String newFileName = String.format("%s-%s", DateUtils.dateTimeNow(), fileName);
            return FileUploadOssUtils.uploadInputStreamToOss(new ByteArrayInputStream(file.getBytes()), picturePath, newFileName, null);
        } catch (Exception e) {
            log.error("上传头像失败", e);
            return null;
        }
    }

    /**
     * 验证验证码
     * @return
     */
    public Boolean verifyCode (String phone) {
        // TODO 验证验证码
        String code = redisCacheUtil.get(phone,String.class);
        return true;
    }

    private String setTokenCache(Long memberId){
        String token = UUIDUtil.getUUID();
        redisCacheUtil.set(String.format("%s%S", Constants.API_TOKEN_CACHE_KEY, token), memberId,Constants.TOKEN_EXPIRE_TIME);
        return token;
    }

    private ApiUserVo setMemberCache(User user){
        ApiUserVo userVo = new ApiUserVo();
        userVo.setAvatar(user.getAvatar());
        userVo.setGender(user.getGender());
        userVo.setNickName(user.getNickName());
        userVo.setPhone(user.getPhone());
        userVo.setUserId(user.getKeyId());
        redisCacheUtil.set(String.format("%s%S", Constants.MEMBER_CACHE_KEY, user.getKeyId()), userVo, Constants.TOKEN_EXPIRE_TIME);
        return userVo;
    }

    private void removeMemberCache(Long memberId){
        String memberKey = String.format("%s%S", Constants.MEMBER_CACHE_KEY, memberId);
        redisCacheUtil.del(memberKey);
    }

    private void removeTokenCache(String token){
        String tokenKey = String.format("%s%S", Constants.API_TOKEN_CACHE_KEY, token);
        redisCacheUtil.del(tokenKey);
    }


    /**
     * 查询用户
     *
     * @param keyId 用户ID
     * @return 用户
     */
    @Override
    public User selectUserById(Long keyId) {
        return userMapper.selectUserById(keyId);
    }

    /**
     * 查询用户列表
     *
     * @param user 用户
     * @return 用户
     */
    @Override
    public List<User> selectUserList(User user) {
        return userMapper.selectUserList(user);
    }

    /**
     * 新增用户
     *
     * @param user 用户
     * @return 结果
     */
    @Override
    public int insertUser(User user) {
        user.setCreateTime(DateUtils.getNowDate());
        user.setKeyId(IdGenerator.getId());
        String password = user.getPassword();
        String newPassword = EncryptUtil.cycleEncryption(password, CommonConst.ENCRYPT_TIMES);
        user.setPassword(newPassword);
        user.setUserType(1);
        user.setAvatar("");
        return userMapper.insertUser(user);
    }

    /**
     * 修改用户
     *
     * @param user 用户
     * @return 结果
     */
    @Override
    public int updateUser(User user) {
        user.setUpdateTime(DateUtils.getNowDate());
        if (StringUtils.isNotEmpty(user.getPassword())) {
            String newPassword = EncryptUtil.cycleEncryption(user.getPassword(), CommonConst.ENCRYPT_TIMES);
            user.setPassword(newPassword);
        } else {
            user.setPassword(null);
        }
        return userMapper.updateUser(user);
    }

    /**
     * 删除用户对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteUserByIds(String ids) {
        return userMapper.deleteUserByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除用户信息
     *
     * @param keyId 用户ID
     * @return 结果
     */
    @Override
    public int deleteUserById(Long keyId) {
        return userMapper.deleteUserById(keyId);
    }
}
